# 闭包：函数中嵌套的函数
# outer的x在inner中被视作一个全局变量，inner会自动将x实参化
# 最后返回的是实参化后的inner，是个实例！
def outer(x):
    def inner(y):
        return x + y

    return inner

func_inner = outer(6)
print(func_inner(5))


# outer(6)返回inner(): return 6 + y，之后再调用inner(5)，得到11


def debug1(func):
    def wrapper():
        print(f"[DEBUG]: enter {func.__name__}()")

        return func()

    return wrapper


def hello1():
    print("hello")


debug1(hello1)()  # 使用闭包的一个例子：调试函数。debug返回wrapper，wrapper的作用是输出一些额外信息之后再执行func()。
# 只要写法是return func()，func必定是最后执行的！


def debug2(func):
    def wrapper():
        print(f"[DEBUG]: enter {func.__name__}()")

        return func()

    return wrapper


@debug2
def hello2():
    print("hello")


hello2()  # 上面那么写太麻烦了，尤其是执行的时候。装饰器是一个语法糖，见上，1和2的作用完全相同！


class logging(object):
    def __init__(self, level):
        self.level = level

    def __call__(self, func):
        def wrapper(*args, **kwargs):
            print("[{0}]: enter {1}()".format(self.level, func.__name__))
            return func(*args, **kwargs)
        return wrapper


@logging(level="TEST")
def hello(a, b, c):
    print(a, b, c)


hello("hello,", "good", "morning")# 最复杂的：带参数的类装饰器！
